package com.itheima.health.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.itheima.health.mapper.OrderMapper;
import com.itheima.health.pojo.Member;
import com.itheima.health.pojo.Order;
import com.itheima.health.service.MemberService;
import com.itheima.health.service.OrderService;
import com.itheima.health.service.OrderSettingService;
import com.itheima.health.utils.date.DateUtils;
import com.itheima.health.utils.redis.RedisUtil;
import com.itheima.health.utils.resources.RedisMessageConstant;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;

@Service
@Transactional

public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    //服务和服务之间的调用
    //此时 订单服务既是服务消费者(相对与会员服务)又是服务的提供者(相对于H5移动端web服务)
    @Reference
    private OrderSettingService orderSettingService;

    @Reference
    private MemberService memberService;

    //提交预约表单到数据库，并返回订单信息用于前端显示
    @Override
    //开启分布式事务
    @LcnTransaction
    public Order add(Map map) {
        //获取手机号
        String telephone = (String)map.get("telephone");
        //1.验证码效验
        //获取表单中的验证码与Redis中的验证码对比
        String codeFromMap = (String) map.get("validateCode");
        String codeFromRedis = RedisUtil.get(RedisMessageConstant.SENDTYPE_ORDER + telephone);
        //用户输入的验证码不能为空
        if (StringUtils.isBlank(codeFromMap)) {
            throw new RuntimeException("验证码必须填写");
        }
        //如果Redis中不存在验证码，说明验证码超时
        if(StringUtils.isBlank(codeFromRedis)){
            throw new RuntimeException("验证码超时");
        }
        //用户输入的验证码与Redis中的验证码不相同，验证码输入错误
        if (!codeFromMap.equals(codeFromRedis)) {
            throw new RuntimeException("验证码输入错误");
        }

        //2.是否预约满
        //根据体检日期比较查询最大预约数和已经预约数
        String orderDate = (String) map.get("orderDate");
        int count = orderSettingService.isOrderOk(orderDate);
        if(count<=0){
            throw new RuntimeException("今日预约满了，请明天再来");
        }
        //判断当前用户是否重复预约
        //查询用户是否是会员，是会员就有可能已经预约，不是会员必定是第一次预约
        Member member = memberService.findMemberByTelement(telephone);
        //获取预约套餐id
        int mid;
        String setmealId = (String) map.get("setmealId");
        int sid = Integer.parseInt(setmealId);
        if (member != null) {
            //是老用户 进一步查询订单表判断套餐 当天是否重复预约
            int orderExist = baseMapper.findOrderBySetmealIdAndOrderDateAndMemberId(sid, orderDate, member.getId());
            mid = member.getId();
            if (orderExist > 0) {
                throw new RuntimeException("今日已经预约");
            }
        } else {
            //不是老会员，更新会员表
            member = new Member();
            member.setName((String) map.get("name"));
            member.setSex((String) map.get("sex"));
            member.setIdCard((String) map.get("idCard"));
            member.setPhoneNumber(telephone);
            member.setRegTime(new Date(System.currentTimeMillis()));
            //注意分布式事务管理不到别的服务接口的save方法。
            //我们必须重写方法，去重写该接口方法上加上@LcnTransaction注解才行
            //memberService.save(member);
            mid= memberService.saveMember(member);

        }
        //可以预约 多表更新 t_order,t_ordersetting,t_member
        //更新预约人数表,预约成功，预约人数+1
        orderSettingService.updateReservationByOrderDate(orderDate);
        //订单表录入
        Order order = new Order();
        order.setMemberId(mid);
        order.setOrderDate(DateUtils.parseString2Date(orderDate, "yyyy-MM-dd"));
        order.setOrderType((String) map.get("orderType"));
        order.setSetmealId(sid);
        order.setOrderStatus("未到诊");
        baseMapper.insert(order);
        return order;
    }


    //移动端根据订单id查询订单信息
    @Override
    public Map findOrderInfoByOrderId(int id) {
        return baseMapper.findOrderInfoByOrderId(id);
    }

}
